package com.rtx.wms.std.handler.so.down;

import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.rtx.common.HttpServletRequestUtil;
import com.rtx.model.dto.edi.EdiInnerRequestDTO;
import com.rtx.wms.customer.common.down.DownLoadService;
import com.rtx.wms.std.common.bean.WmsConstant;
import com.rtx.wms.std.ctclass.ClassHolder;
import com.rtx.wms.std.qm.bean.RtxQMResponse;
import com.rtx.wms.std.qm.service.ReceiverinfoQueryService;
import com.rtx.wms.std.sku.bean.po.Sku;
import com.rtx.wms.std.so.bean.ApiOrderdetail;
import com.rtx.wms.std.so.bean.ApiOrders;
import com.rtx.wms.std.so.service.ApiOrdersService;
import com.rtx.wms.std.so.service.OrdersService;
import com.rtx.wms.std.validation.so.OrdersValidation;

/**
 * 出库单下发
 */
@SuppressWarnings("all")
public abstract class AbstractOrdersDownHandler implements DownLoadService{

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected ApiOrdersService apiOrdersService;

    @Autowired
    protected OrdersValidation ordersValidation;

    @Autowired
    protected OrdersService ordersService;

    @Autowired
    protected ReceiverinfoQueryService receiverinfoQueryService;

    /**
     * 创建出库单
     * @param apiOrders
     */
    public String create(HttpServletRequest request){
        RtxQMResponse res = new RtxQMResponse();
        ApiOrders apiOrders = null;
        try {
        	String requestStr = HttpServletRequestUtil.getHttpBody(request);
    		EdiInnerRequestDTO dto = JSON.parseObject(requestStr, EdiInnerRequestDTO.class);
    		
        	if(StringUtils.hasLength(dto.getConfig().getPreconfig())) {
        		//预处理
            	preHandle(request);
        	}
        	
        	if(apiOrders == null) {
        		String targetJson = dto.getTagetjson();
        		
        		apiOrders = addExternalColumns(targetJson,dto);
        	}
        	
        	//字段映射后处理
        	afterHandle(apiOrders,requestStr);
        	
            //验证出库单
            validationApiOrders(apiOrders);
            
            //执行插入之前
            preinsert(apiOrders,request);
            
            //写入中间表
            insertApiOrders(apiOrders,dto);
            
            res.setSuccess("成功");
        } catch (Exception e) {
            logger.error("出库单：{}，创建异常：",e);
            res.setFailure(e.getMessage());
        }
        return JSON.toJSONString(res);
    }
    
    /**
     * 插入表之前处理客制化新增字段
     * @throws InvocationTargetException 
     * @throws Exception 
     * 
     */
    public ApiOrders addExternalColumns(String targetJson,EdiInnerRequestDTO dto){
    	ApiOrders head = null;
    	try {
    		Long apiid =  dto.getConfig().getTargetApi().getId();
    		Map<String,Class> map = ClassHolder.apiconfigClassMap.get(apiid+"");
    		if(map != null) {
    			Class headclass =map.get("main");
    			Class subclass =map.get("sub");
    			head = (ApiOrders) JSON.parseObject(targetJson,headclass);
    			List<ApiOrderdetail> sub = JSON.parseArray(JSON.parseObject(targetJson).getString("details") ,subclass);
    			head.setDetails(sub);
    		}else {
    			head = JSON.parseObject(targetJson,ApiOrders.class);
    		}
    	} catch (Exception e) {
    		head = JSON.parseObject(targetJson,ApiOrders.class);
    	}


    	return head;
    }
    
    //转换字段后处理逻辑
    protected abstract void afterHandle(ApiOrders apiOrders,String requestStr);

    /**
     * 进入处理方法之前
     */
    protected abstract ApiOrders preHandle(HttpServletRequest request);
    
    /**
     * 在insert 之后
     * @param request
     * @return
     */
    protected abstract void preinsert(ApiOrders o,HttpServletRequest request);
    
    /**
     * 写入出库单
     * @param apiOrders
     */
    protected void insertApiOrders(ApiOrders apiOrders,EdiInnerRequestDTO dto) {
        //根据“外部单号”查询ORDERS表中是否存在，如果没有就新建一个WMS出库单。
        ordersService.handlerExistsOrders(apiOrders.getWhseid(),apiOrders.getExternorderkey());
        //新增出库单
        apiOrdersService.addApiOrders("ris_edi",apiOrders,dto);
    }

    /**
     * 验证出库订单
     * @param apiOrders
     */
    protected void validationApiOrders(ApiOrders apiOrders) {
        //货主
        if(!StringUtils.hasText(apiOrders.getStorerkey())){
            apiOrders.setStorerkey(apiOrders.getDetails().get(0).getStorerkey());
        }
        
        //校验TOTALORDERLINES总行数与明细行数不一致，写入“XX单总行数不一致”报错数据到ERRMSG中。
        //Assert.isTrue(apiOrders.getTOTALORDERLINES().intValue() == apiOrders.getDetails().size(),"出库单" + apiOrders.getEXTERNORDERKEY() + "总行数不一致");
        Set<String> skuSet = new HashSet<>();
        //统计订单总量
        Double totalQty = 0D;
        //统计不不参与拣货数量
        Double noTPickQty = 0D;
        for(ApiOrderdetail detail : apiOrders.getDetails()){
            //仓库
            detail.setWhseid(apiOrders.getWhseid());
            //单号
            detail.setExternorderkey(apiOrders.getExternorderkey());
            //货主
            detail.setStorerkey(apiOrders.getStorerkey());
            //判断订单中SKU是否重复，是报错“同一订单SKU不能重复” 报错数据到ERRMSG中
            if(skuSet.contains(detail.getSku())){
                throw new RuntimeException("SKU：" + detail.getSku() + "重复");
            }else{
                skuSet.add(detail.getSku());
            }
            //校验接口表中的SKU是否在该仓库下存在，不存在终止程序，写入“SKU不存在”报错数据到ERRMS
            Sku sku = ordersValidation.validationSku(WmsConstant.ENTERPRISE, detail.getStorerkey(), detail.getSku(), true);
            //ORDERDETAIL.RTXNOTPICK不参与拣货，根据SKU表的RTXNOTPICK值写入
            detail.setRtxnotpick(sku.getRtxnotpick());
            //单位
            detail.setUom("EA");
            //包装
            detail.setPackkey(sku.getPackkey());
            //RTXNOTPICKNUMBER不参与拣货数量，根据明细的ORDERDETAIL.RTXNOTPICK=1统计SHIPPEDQTY数量
            if("1".equals(sku.getRtxnotpick())){
                noTPickQty += detail.getOriginalqty();
            }
            detail.setAllocatestrategykey(sku.getAllowconsolidation());
            detail.setAllowconsolidation(sku.getAllowconsolidation());
            totalQty += detail.getOriginalqty();
        }
        apiOrders.setTotalqty(totalQty+"");
        apiOrders.setRtxnotpicknumber(noTPickQty + "");
        apiOrders.setTotalorderlines(apiOrders.getDetails().size()+"");
        //特定验证
        validationSpecific(apiOrders);
    }

    /**
     * 特定验证
     * @param apiOrders
     */
    protected abstract void validationSpecific(ApiOrders apiOrders);
}
